package cec726

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"strconv"
	"szkis/simu/utils"
	"szkis/wrap/lg"
)

// 中电技术的PMC-D726M， modbus协议

var DATA_CURRENT = []byte{0x03, 0x00, 0x10, 0x00, 0x08}
var DATA_KW = []byte{0x03, 0x03, 0xe8, 0x00, 0x04}
var DT_KW = 1
var DT_I = 2 

type Cec726Packet struct {
	Addr     byte   // 地址
	Func     byte   // 功能码
	Data     []byte // 数据部分
	Length   int    // 数据长度
	DataType int    // 数据类型, 1=电量  2=电流

	KwImport    float64 // 有功电量
	KwExport    float64 // 无功功率
	Ia          float64 // 电流A
	Ib          float64 // 电流B
	Ic          float64 // 电流C
	Iaverage    float64 // 平均电流
	SuccessFlag bool    // 解析成功标志
}

// 读取电流的报文 01 03 00 10 00 08 45 c9
func ReadCurrent(addr string) []byte {
	// 取末2位十进制作为地址
	str := addr[len(addr)-2:]
	iAddr, _ :=strconv.Atoi(str)

	buf := bytes.Buffer{}
	buf.WriteByte(byte(iAddr))
	buf.Write(DATA_CURRENT)
	// CRC
	buf.Write(Crc16(buf.Bytes()))
	// lg.Info(utils.EncodeToStringSep(buf.Bytes(), byte(' ')))

	return buf.Bytes()
}

// 抄表
func ReadMeter(addr string) []byte {
	buf := bytes.Buffer{}

	// 取末2位十进制作为地址
	str := addr[len(addr)-2:]
	iAddr, _ :=strconv.Atoi(str)

	buf.WriteByte(byte(iAddr))
	buf.Write(DATA_KW)	
	// CRC
	buf.Write(Crc16(buf.Bytes()))

	// lg.Info(utils.EncodeToStringSep(buf.Bytes(), byte(' ')))
	return buf.Bytes()
}

// 读取电量的报文 01 03 03 e8 00 04 c4 79
func ReadKW(addr int) []byte {
	buf := bytes.Buffer{}
	buf.WriteByte(byte(addr))
	buf.Write(DATA_KW)	
	// CRC
	buf.Write(Crc16(buf.Bytes()))

	return buf.Bytes()
}


// CRC16
func Crc16(dat []byte) []byte {
	var crc_reg, crc_gen uint32
	crc_reg, crc_gen = 0xFFFF, 0xA001

	for i, l := 0, len(dat); i < l; i++ {
		crc_reg = (uint32(dat[i]) & 0xff) ^ crc_reg
		for j := 8; j > 0; j-- {
			if crc_reg&0x01 == 1 {
				crc_reg >>= 1
				crc_reg ^= crc_gen
			} else {
				crc_reg >>= 1
			}
		}
	}

	buf := make([]byte, 2)
    binary.LittleEndian.PutUint16(buf, uint16(crc_reg))
    return buf
}

// 解包
func ParsePacket(data []byte, dataType int) *Cec726Packet {
	ret := &Cec726Packet{
		Addr:        data[0],
		Length:      int(data[2]),
		DataType:    dataType,
		SuccessFlag: false,
	}

	lg.Info(utils.EncodeToStringSep(data, byte(' ')))

	ret.Data = data[3:ret.Length]
	if dataType == DT_KW {
		ret.ParseKw()
	} else 
	if dataType == DT_I {
		ret.ParseIabc()
	}

	return ret
}

// 转为浮点数
func formatFloat(data []byte, scale int) float64 {
	// lg.Info("truncFloat", s)
	// 1. 转hex
	valStr := utils.BytesToHex(data)
	//  lg.Info("truncFloat", valStr)
	// 2. 转整数
	num,err := strconv.ParseInt(valStr,16, 32)
	if err != nil {
		return 0 
	}
	// 3. 整数转浮点数
	ret :=  float64(num)
	for i:=0; i<scale; i++ {
		ret = 0.1 * ret 
	}

	// 保留scale位小数
	ret = truncFloat(ret, scale)

	return ret 
}

// 保留位数
func truncFloat(src float64, scale int) float64{
	s := "%." + strconv.Itoa(scale) + "f"
	// lg.Info("truncFloat", s)
	ret, _ := strconv.ParseFloat(fmt.Sprintf(s, src), 64)
	return ret
}

// 解析电量
func (me *Cec726Packet) ParseKw() {
	// 电量-系数为0.1
	me.KwImport = formatFloat(me.Data[0:4], 1)
	me.KwExport = formatFloat(me.Data[4:8], 1)
	me.SuccessFlag = true
}

// 解析电流块
func (me *Cec726Packet) ParseIabc() {
	// 电流-系数为0.001
	me.Ia = formatFloat(me.Data[0:4], 3)
	me.Ib = formatFloat(me.Data[4:8], 3)
	me.Ic = formatFloat(me.Data[8:12], 3)
	me.Iaverage = formatFloat(me.Data[12:16], 3)
	me.SuccessFlag = true
}